


from portio import outb,inb,iopl

class WinbondInputOutput(object):
    """
    Pristup k winbond gpio - servisni modul.
    Pavel Dufek, 2010, TPC.    
    """
    
    def __init__(self):        
        #  Predpokladane pouziti:
        # - na zacatku programu zavolat initAutomatGpio - musi vratit True
        # - pak volat opakovane nactiAutomatGpio a bity zjistovat pomoci & GPIO24_DVERE_MASK,
        #   GPIO23_230V_MASK
            # definice adres Winbond        
        self.WINBOND_PORT=0x2e
            
        self.REG_LDN_SEL=0x07
        self.REG_GPIO_DIRECTION=0xf0
        self.REG_GPIO_DATA=0xf1
        self.REG_GPIO_INVERT=0xf0
        
        self.LDN_GPIO1=0x07
        self.LDN_GPIO2=0x08
        self.LDN_GPIO3=0x09
        
        # Maska nastavujici GPIO23-GPIO27 jako vstupy, z toho GPIO23-GPIO25 jsou piny 15-17
        # konektoru Alix1 J11.
        self.GPIO23_TO_27_INPUTS_MASK=0xf8
        self.initAutomatGpio()
        self.nactiAutomatGpio()

    def _regRead(self, port, reg):
        # Precte a vrati hodnotu registru "reg" z Winbondu na portu "port".
        outb(reg, port)
        return inb(port + 1)

    def _regWrite(self, port, reg, val):
        # Zapise hodnotu "val" do registru "reg" do Winbondu na portu "port".
        outb(reg, port)
        outb(val, port + 1)
    
    def _enterConfModeWinbond(self, port):
        # Aktivuje pristup k registrum Winbondu na portu "port".
        outb(0x87, port)
        outb(0x87, port)
    
    def _exitConfModeWinbond(self, port):
        # Ukonci pristup k registrum Winbondu na portu "port".
        outb(0xaa, port)
    
    def _enterGenericPortAccess(self):
        # Aktivuje pristup k io portum obecne - nutno volat na zacatku.
        # Pokud vrati False, je to cele hodne spatne a zadne gpio nema sanci jet - nejsou prava na porty.
        rc=iopl(3)
        if rc:
            return False
        return True
   

    
    def initAutomatGpio(self):
        # Nahodi pristup k portum a nastavi GP27,26,25,24,23 na vstupy.
        # Vraci True, kdyz pristup ok. 
        if not self._enterGenericPortAccess():
            return False
        self._enterConfModeWinbond(self.WINBOND_PORT)
        self._regWrite(self.WINBOND_PORT, self.REG_LDN_SEL, self.LDN_GPIO2)
        self._regWrite(self.WINBOND_PORT, self.REG_GPIO_DIRECTION, self.GPIO23_TO_27_INPUTS_MASK)
        self._exitConfModeWinbond(self.WINBOND_PORT)
        return True
    
    def nactiAutomatGpio(self):        
        # Aktivuje Winbond a nacte registr stavu GPIO2 pinu
        self._enterConfModeWinbond(self.WINBOND_PORT)
        self._regWrite(self.WINBOND_PORT, self.REG_LDN_SEL, self.LDN_GPIO2)
        stavovyBajt=self._regRead(self.WINBOND_PORT, self.REG_GPIO_DATA)
        self._exitConfModeWinbond(self.WINBOND_PORT)
        '''
        get the bitvalue of denary (base 10) number n at the equivalent binary
        position p (binary count starts at position 0 from the right)
        '''
        napeti_GPIO = (stavovyBajt >> 3) & 1 # napeti je pripojeno na GPIO 15, logicka 1 == napeti pripojeno
        dvere_GPIO = (stavovyBajt >> 5) & 1 # spinac dveri je pripojen na GPIO 17 proti zemi, logicka 1 znamena dvere otevreny
        
        if napeti_GPIO: # logicka uroven na GPIO 15 je 1
            self._napajeciNapetiPripojeno = 1
        else:
            self._napajeciNapetiPripojeno = 0
            
        
        if dvere_GPIO: # logicka uroven na GPIO 17 je 1
            self.dverniKontaktRozepnut = self._dvereOtevreny = 1
            self.dverniKontaktSepnut = self._dvereZavereny = 0            
        else:
            self.dverniKontaktRozepnut = self._dvereOtevreny = 0
            self.dverniKontaktSepnut = self._dvereZavereny = 1
        


                
#    dvereOtevreny= property(fget = lambda self: self.nactiAutomatGpio(poradoveCisloBitu=3))    
#    napajeciNapetiPripojeno = property(fget = lambda self: self.nactiAutomatGpio(poradoveCisloBitu=4))    
    
    def napajeciNapetiPripojeno(self):
        return self._napajeciNapetiPripojeno
#        
    def dvereOtevreny(self):
        return self._dvereOtevreny
        
if __name__=='__main__':
    periferie = WinbondInputOutput()
#    periferie.nactiAutomatGpio()
    if periferie._dvereOtevreny:
        print "DVERE OTEVRENY" 
    else:
        print "DVERE ZAVRENY"
    # 0 znamena dvere zavreny
    # 1 znamena dvere otevreny
    # jazyckove rele je pripojeno mezi vstup 17 (je "pulled up") a GND
    # kdyz jsou dvere zavreny, priblizi se magnet k jazyckovemu rele, kontakty jsou spojeny 
    # vstup 17 je uzemnen a hlasi logickou 0

    # indikace Vcc je pripojena na vstup 15 ("pulled down") 
    # kdyz je Vcc pripojeno, je na vstupu 15 5V a vstup hlasi logickou 1
    if periferie._napajeciNapetiPripojeno:
        print "230V pripojeno"
    else:
        print "230V neni pripojeno"
